package com.bookshop.service.impl;

import com.bookshop.entity.*;
import com.bookshop.mapper.BookMapper;
import com.bookshop.mapper.CartMapper;
import com.bookshop.mapper.OrderMapper;
import com.bookshop.scheduler.JobDetailAndTriggerService;
import com.bookshop.service.OrderService;
import com.bookshop.util.OrderUtil;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import lombok.extern.slf4j.Slf4j;
import org.quartz.SchedulerException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.data.redis.core.RedisTemplate;

import javax.annotation.Resource;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.concurrent.TimeUnit;

/**
 * (Order)表服务实现类
 *
 * @author hk
 * @since 2024-01-17 09:41:39
 */
@Service
@Slf4j
public class OrderServiceImpl implements OrderService {
    @Resource
    private OrderMapper orderMapper;
    @Resource
    private BookMapper bookMapper;
    @Resource
    private CartMapper cartMapper;
    @Resource
    private JobDetailAndTriggerService jobDetailAndTriggerService;
    @Resource
    private RedisTemplate<String, String> redisTemplate;
    private final String ORDER_ID_SET_KEY = "processed_order_ids";

    @Autowired
    public OrderServiceImpl(OrderMapper orderMapper , BookMapper bookMapper , CartMapper cartMapper, RedisTemplate<String, String> redisTemplate) {
        this.orderMapper = orderMapper;
        this.bookMapper = bookMapper;
        this.cartMapper = cartMapper;
        this.redisTemplate = redisTemplate;
    }

    @Override
    public Map<String , String> addToOrder(List<BookWithNum> books, int userId) throws SchedulerException {
        SimpleDateFormat formatter= new SimpleDateFormat("yyyy-MM-dd HH:mm:ss z");
        Date date = new Date(System.currentTimeMillis());
        Order order = new Order();
        order.setOrderNo(OrderUtil.getNo());
        double totalAmount = 0;//bigD
        double price = 0;
        Map<String , String> resultMap = new HashMap<>();

        if (isOrderProcessed(order.getOrderNo())) {
            // 订单已处理，重复请求，不再进行处理
            return resultMap;
        }

        for(BookWithNum book : books)
        {
            price = bookMapper.getBookPrice(String.valueOf(book.getBook().getId()));
            totalAmount += price * book.getBookNum();
        }

        order.setTotalAmount(totalAmount);
        order.setCreateTime(date);
        order.setPayStatus(0);

        int result = orderMapper.addToOrder(order.getOrderNo() , order.getTotalAmount() , order.getCreateTime() , order.getPayStatus() , userId);
        addProcessedOrder(order.getOrderNo(),5, TimeUnit.MINUTES);


        jobDetailAndTriggerService.InitPayStatusQuartz(order.getOrderNo());

        if(result == 0)
        {
            return resultMap;
        }
        //获得订单号
        int orderId = orderMapper.getOrderId(order.getOrderNo());

        for(BookWithNum book : books)
        {
            orderMapper.addBookToOrder(orderId , Integer.parseInt(String.valueOf(book.getBook().getId() )), bookMapper.getBookPrice(String.valueOf(book.getBook().getId())) , book.getBookNum());
            cartMapper.deleteFromCart(userId , Integer.parseInt(String.valueOf(book.getBook().getId())));
        }

        resultMap.put("orderNo" , order.getOrderNo());
        resultMap.put("totalAmount" , String.valueOf(totalAmount));
        String creatTime = formatter.format(date);
        resultMap.put("creatTime" , creatTime);
        resultMap.put("orderId" , String.valueOf(orderId));
        return resultMap;
    }

    @Override
    public int deleteOrder(String orderNo) {
        int orderId = orderMapper.getOrderId(orderNo);
        int result = orderMapper.deleteOrder(orderNo);
        orderMapper.deleteBookFromOrder(orderId);
        return result;
    }

    @Override
    public int updatePayStatus(String orderNo, int payStatus) {
        int result = 0;
        int payStatus_1 = orderMapper.getPayStatus(orderNo);
        Date date = new Date(System.currentTimeMillis());

        if(payStatus_1 == 0)
        {
            result = orderMapper.updatePayStatus(orderNo , payStatus , date);
            if(result == 1)
            {
                //支付成功
                return 1;
            }
            else
            {
                //支付失败
                return 0;
            }
        }
        else
        {
            //订单超时
           return 2;
        }
    }

    @Override
    public BookList getOrderList(int orderId , int pageNum , int pageSize) {

        PageHelper.startPage(pageNum , pageSize);

        List<Book> bookList = orderMapper.getOrderList(orderId);

        PageInfo<Book> pageInfo = new PageInfo<>(bookList);
        return new BookList(pageInfo.getList() , pageInfo.getTotal() , pageInfo.getPages());
    }

    @Override
    public Order getOrderInfo(int orderId) {
        //获取订单的信息
        Order order = orderMapper.getOrderInfo(orderId);
        return order;
    }

    @Override
    public List<Order> searchByStatus(int payStatus, int userId) {
        //获得用户的所有符合订单状态的订单
        List<Order> orderList = orderMapper.searchByStatus(payStatus , userId);

        return orderList;
    }

    @Override
    public OrderList getAllOrder(int userId, int pageNum, int pageSize) {
        PageHelper.startPage(pageNum , pageSize);

        List<Order> orderList = orderMapper.getAllOrder(userId);

        PageInfo<Order> pageInfo = new PageInfo<>(orderList);
        return new OrderList(pageInfo.getList() , pageInfo.getTotal() , pageInfo.getPages());
    }

    /**
     * 检查订单号是否已经存在于已处理订单的集合中。
     *
     * @param orderId 订单号
     * @return true 表示订单已处理，false 表示订单未处理
     */
    private boolean isOrderProcessed(String orderId ) {
        Set<String> processedOrderIds = redisTemplate.opsForSet().members(ORDER_ID_SET_KEY);
        return processedOrderIds != null && processedOrderIds.contains(orderId);
    }

    /**
     * 将订单号添加到已处理订单的集合中。
     *
     * @param orderId 订单号
     */
    private void addProcessedOrder(String orderId, long duration, TimeUnit timeUnit) {
        redisTemplate.opsForSet().add(ORDER_ID_SET_KEY, orderId);
        redisTemplate.expire(ORDER_ID_SET_KEY, duration, timeUnit);
    }
}
